home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-11-24 | 54.3 KB | 2,423 lines |
- Newsgroups: comp.sources.misc
- From: jfh@rpp386.Cactus.ORG (John F Haugh II)
- Subject: v26i061: shadow - Shadow Password Suite, Part08/11
- Message-ID: <1991Nov24.185207.20553@sparky.imd.sterling.com>
- X-Md4-Signature: a43c652bfff931c20d58afe8ef696479
- Date: Sun, 24 Nov 1991 18:52:07 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: jfh@rpp386.Cactus.ORG (John F Haugh II)
- Posting-number: Volume 26, Issue 61
- Archive-name: shadow/part08
- Environment: UNIX
- Supersedes: shadow-2: Volume 06, Issue 22-24
-
- #! /bin/sh
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: chpasswd.c dpmain.c faillog.c groupdel.c gshadow.c
- # obscure.c pwconv.c setup.c sulogin.c useradd.1 utmp.c
- # Wrapped by kent@sparky on Sun Nov 24 11:03:43 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 8 (of 11)."'
- if test -f 'chpasswd.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'chpasswd.c'\"
- else
- echo shar: Extracting \"'chpasswd.c'\" \(5160 characters\)
- sed "s/^X//" >'chpasswd.c' <<'END_OF_FILE'
- X/*
- X * Copyright 1990, 1991, John F. Haugh II
- X * All rights reserved.
- X *
- X * Permission is granted to copy and create derivative works for any
- X * non-commercial purpose, provided this copyright notice is preserved
- X * in all copies of source code, or included in human readable form
- X * and conspicuously displayed on all copies of object code or
- X * distribution media.
- X *
- X * chpasswd - update passwords in batch
- X *
- X * chpasswd reads standard input for a list of colon separated
- X * user names and new passwords. the appropriate password
- X * files are updated to reflect the changes. because the
- X * changes are made in a batch fashion, the user must run
- X * the mkpasswd command after this command terminates since
- X * no password updates occur until the very end.
- X */
- X
- X#include <stdio.h>
- X#include "pwd.h"
- X#include <fcntl.h>
- X#include <string.h>
- X#include "config.h"
- X#ifdef SHADOWPWD
- X#include "shadow.h"
- X#endif
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)chpasswd.c 3.4 08:57:30 6/10/91";
- X#endif
- X
- Xchar *Prog;
- X
- Xextern char *pw_encrypt();
- Xextern char *l64a();
- X
- X/*
- X * If it weren't for the different structures and differences in how
- X * certain fields were manipulated, I could just use macros to replace
- X * the function calls for the different file formats. So I make the
- X * best of things and just use macros to replace a few of the calls.
- X */
- X
- X#ifdef SHADOWPWD
- X#define pw_lock spw_lock
- X#define pw_open spw_open
- X#define pw_close spw_close
- X#define pw_unlock spw_unlock
- X#endif
- X
- X/*
- X * usage - display usage message and exit
- X */
- X
- Xusage ()
- X{
- X fprintf (stderr, "usage: %s\n", Prog);
- X exit (1);
- X}
- X
- Xmain (argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X char buf[BUFSIZ];
- X char *name;
- X char *newpwd;
- X char *cp;
- X#ifdef SHADOWPWD
- X struct spwd *sp;
- X struct spwd newsp;
- X struct spwd *spw_locate();
- X#else
- X struct passwd *pw;
- X struct passwd newpw;
- X struct passwd *pw_locate();
- X char newage[5];
- X#endif
- X int errors = 0;
- X int line = 0;
- X long now = time ((long *) 0) / (24L*3600L);
- X
- X if (Prog = strrchr (argv[0], '/'))
- X Prog++;
- X else
- X Prog = argv[0];
- X
- X if (argc != 1)
- X usage ();
- X
- X /*
- X * Lock the password file and open it for reading. This will
- X * bring all of the entries into memory where they may be
- X * updated.
- X */
- X
- X if (! pw_lock ()) {
- X fprintf (stderr, "%s: can't lock password file\n", Prog);
- X exit (1);
- X }
- X if (! pw_open (O_RDWR)) {
- X fprintf (stderr, "%s: can't open password file\n", Prog);
- X exit (1);
- X }
- X
- X /*
- X * Read each line, separating the user name from the password.
- X * The password entry for each user will be looked up in the
- X * appropriate file (shadow or passwd) and the password changed.
- X * For shadow files the last change date is set directly, for
- X * passwd files the last change date is set in the age only if
- X * aging information is present.
- X */
- X
- X while (fgets (buf, sizeof buf, stdin) != (char *) 0) {
- X line++;
- X if (cp = strrchr (buf, '\n')) {
- X *cp = '\0';
- X } else {
- X fprintf (stderr, "%s: line %d: line too long\n",
- X Prog, line);
- X errors++;
- X continue;
- X }
- X
- X /*
- X * The username is the first field. It is separated
- X * from the password with a ":" character which is
- X * replaced with a NUL to give the new password. The
- X * new password will then be encrypted in the normal
- X * fashion with a new salt generated.
- X */
- X
- X name = buf;
- X if (cp = strchr (name, ':')) {
- X *cp++ = '\0';
- X } else {
- X fprintf (stderr, "%s: line %d: missing new password\n",
- X Prog, line);
- X errors++;
- X continue;
- X }
- X newpwd = cp;
- X cp = pw_encrypt (newpwd, (char *) 0);
- X
- X /*
- X * Get the password file entry for this user. The user
- X * must already exist.
- X */
- X
- X#ifdef SHADOWPWD
- X if (! (sp = spw_locate (name)))
- X#else
- X if (! (pw = pw_locate (name)))
- X#endif
- X {
- X fprintf (stderr, "%s: line %d: unknown user %s\n",
- X Prog, line, name);
- X errors++;
- X continue;
- X }
- X
- X /*
- X * The freshly encrypted new password is merged into
- X * the user's password file entry and the last password
- X * change date is set to the current date.
- X */
- X
- X#ifdef SHADOWPWD
- X newsp = *sp;
- X newsp.sp_pwdp = cp;
- X newsp.sp_lstchg = now;
- X#else
- X newpw = *pw;
- X newpw.pw_passwd = cp;
- X#ifdef ATT_AGE
- X if (newpw.pw_age[0]) {
- X strcpy (newage, newpw.pw_age);
- X strcpy (newage + 2, l64a (now / 7));
- X newpw.pw_age = newage;
- X }
- X#endif
- X#endif
- X
- X /*
- X * The updated password file entry is then put back
- X * and will be written to the password file later, after
- X * all the other entries have been updated as well.
- X */
- X
- X#ifdef SHADOWPWD
- X if (! spw_update (&newsp))
- X#else
- X if (! pw_update (&newpw))
- X#endif
- X {
- X fprintf (stderr, "%s: line %d: cannot update password entry\n",
- X Prog, line);
- X errors++;
- X continue;
- X }
- X }
- X
- X /*
- X * Any detected errors will cause the entire set of changes
- X * to be aborted. Unlocking the password file will cause
- X * all of the changes to be ignored. Otherwise the file is
- X * closed, causing the changes to be written out all at
- X * once, and then unlocked afterwards.
- X */
- X
- X if (errors) {
- X fprintf (stderr, "%s: error detected, changes ignored\n", Prog);
- X pw_unlock ();
- X exit (1);
- X }
- X if (! pw_close ()) {
- X fprintf (stderr, "%s: error updating password file\n", Prog);
- X exit (1);
- X }
- X (void) pw_unlock ();
- X}
- END_OF_FILE
- if test 5160 -ne `wc -c <'chpasswd.c'`; then
- echo shar: \"'chpasswd.c'\" unpacked with wrong size!
- fi
- # end of 'chpasswd.c'
- fi
- if test -f 'dpmain.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dpmain.c'\"
- else
- echo shar: Extracting \"'dpmain.c'\" \(4250 characters\)
- sed "s/^X//" >'dpmain.c' <<'END_OF_FILE'
- X/*
- X * Copyright 1990, 1991 John F. Haugh II
- X * All rights reserved.
- X *
- X * Permission is granted to copy and create derivative works for any
- X * non-commercial purpose, provided this copyright notice is preserved
- X * in all copies of source code, or included in human readable form
- X * and conspicuously displayed on all copies of object code or
- X * distribution media.
- X */
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <stdio.h>
- X#include <fcntl.h>
- X#ifdef BSD
- X#include <strings.h>
- X#else
- X#include <string.h>
- X#endif
- X#include "dialup.h"
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)dpmain.c 3.4 17:31:55 8/4/91";
- X#endif
- X
- X#ifdef USG
- X#define bzero(p,l) memset(p, 0, l)
- X#endif
- X
- X#define DTMP "/etc/d_passwd.tmp"
- X
- X/*
- X * Prompts and messages go here.
- X */
- X
- X#define PASS1 "Shell password:"
- X#define PASS2 "re-enter Shell password:"
- X#define NOMATCH "%s: Passwords do not match, try again.\n"
- X#define NOFOUND "%s: Shell %s not found.\n"
- X
- Xint aflg;
- Xint dflg;
- Xchar *Prog;
- X
- Xextern char *pw_encrypt();
- Xextern char *getpass();
- X
- Xusage ()
- X{
- X fprintf (stderr, "Usage: %s [ -(a|d) ] shell\n", Prog);
- X exit (1);
- X}
- X
- Xmain (argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X struct dialup *dial;
- X struct dialup dent;
- X struct stat sb;
- X FILE *fp;
- X char *shell;
- X char *cp;
- X char pass[BUFSIZ];
- X int fd;
- X int found = 0;
- X int opt;
- X extern int optind;
- X extern char *optarg;
- X
- X if (Prog = strrchr (argv[0], '/'))
- X Prog++;
- X else
- X Prog = argv[0];
- X
- X while ((opt = getopt (argc, argv, "a:d:")) != EOF) {
- X switch (opt) {
- X case 'a':
- X aflg++;
- X shell = optarg;
- X break;
- X case 'd':
- X dflg++;
- X shell = optarg;
- X break;
- X default:
- X usage ();
- X }
- X }
- X if (! aflg && ! dflg)
- X aflg++;
- X
- X if (! shell) {
- X if (optind >= argc)
- X usage ();
- X else
- X shell = argv[optind];
- X }
- X if (aflg + dflg != 1)
- X usage ();
- X
- X /*
- X * Add a new shell to the password file, or update an existing
- X * entry. Begin by getting an encrypted password for this
- X * shell.
- X */
- X
- X if (aflg) {
- X int tries = 3;
- X
- X dent.du_shell = shell;
- X dent.du_passwd = "";
- X
- Xagain:
- X if (! (cp = getpass (PASS1)))
- X exit (1);
- X
- X strcpy (pass, cp);
- X bzero (cp, strlen (cp));
- X
- X if (! (cp = getpass (PASS2)))
- X exit (1);
- X
- X if (strcmp (pass, cp)) {
- X bzero (pass, strlen (pass));
- X bzero (cp, strlen (cp));
- X fprintf (stderr, NOMATCH, Prog);
- X
- X if (--tries)
- X goto again;
- X
- X exit (1);
- X }
- X bzero (cp, strlen (cp));
- X dent.du_passwd = pw_encrypt (pass, (char *) 0);
- X bzero (pass, strlen (pass));
- X }
- X
- X /*
- X * Create the temporary file for the updated dialup password
- X * information to be placed into. Turn it into a (FILE *)
- X * for use by putduent().
- X */
- X
- X if ((fd = open (DTMP, O_CREAT|O_EXCL|O_RDWR, 0600)) < 0) {
- X sprintf (pass, "%s: can't create %s", Prog, DTMP);
- X perror (pass);
- X exit (1);
- X }
- X if (! (fp = fdopen (fd, "r+"))) {
- X sprintf (pass, "%s: can't open %s", Prog, DTMP);
- X perror (pass);
- X exit (1);
- X }
- X
- X /*
- X * Scan the dialup password file for the named entry,
- X * copying out other entries along the way. Copying
- X * stops when a match is found or the file runs out.
- X */
- X
- X while (dial = getduent ()) {
- X if (strcmp (dial->du_shell, shell) == 0) {
- X found = 1;
- X break;
- X }
- X if (putduent (dial, fp))
- X goto failure;
- X }
- X
- X /*
- X * To delete the entry, just don't copy it. To update
- X * the entry, output the modified version - works with
- X * new entries as well.
- X */
- X
- X if (dflg && ! found) {
- X fprintf (stderr, NOMATCH, Prog, shell);
- X exit (1);
- X }
- X if (aflg)
- X if (putduent (&dent, fp))
- X goto failure;
- X
- X /*
- X * Now copy out the remaining entries. Flush and close the
- X * new file before doing anything nasty to the existing
- X * file.
- X */
- X
- X
- X while (dial = getduent ())
- X if (putduent (dial, fp))
- X goto failure;
- X
- X if (fflush (fp))
- X goto failure;
- X
- X fclose (fp);
- X
- X /*
- X * If the original file did not exist, we must create a new
- X * file with owner "root" and mode 400. Otherwise we copy
- X * the modes from the existing file to the new file.
- X *
- X * After this is done the new file will replace the old file.
- X */
- X
- X if (! stat (DIALPWD, &sb)) {
- X chown (DTMP, sb.st_uid, sb.st_gid);
- X chmod (DTMP, sb.st_mode);
- X unlink (DIALPWD);
- X } else {
- X chown (DTMP, 0, 0);
- X chmod (DTMP, 0400);
- X }
- X link (DTMP, DIALPWD);
- X unlink (DTMP);
- X
- X sync ();
- X exit (0);
- X
- Xfailure:
- X unlink (DTMP);
- X exit (1);
- X}
- END_OF_FILE
- if test 4250 -ne `wc -c <'dpmain.c'`; then
- echo shar: \"'dpmain.c'\" unpacked with wrong size!
- fi
- # end of 'dpmain.c'
- fi
- if test -f 'faillog.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'faillog.c'\"
- else
- echo shar: Extracting \"'faillog.c'\" \(4879 characters\)
- sed "s/^X//" >'faillog.c' <<'END_OF_FILE'
- X/*
- X * Copyright 1989, 1990, John F. Haugh II
- X * All rights reserved.
- X *
- X * Permission is granted to copy and create derivative works for any
- X * non-commercial purpose, provided this copyright notice is preserved
- X * in all copies of source code, or included in human readable form
- X * and conspicuously displayed on all copies of object code or
- X * distribution media.
- X */
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <stdio.h>
- X#include "pwd.h"
- X#include <time.h>
- X#ifndef BSD
- X#include <string.h>
- X#include <memory.h>
- X#else
- X#include <strings.h>
- X#define strchr index
- X#define strrchr rindex
- X#endif
- X#include "config.h"
- X#include "faillog.h"
- X
- X#ifndef lint
- Xstatic char _sccsid[] = "@(#)faillog.c 3.2 08:44:11 9/12/91";
- X#endif
- X
- XFILE *fail; /* failure file stream */
- Xoff_t user; /* one single user, specified on command line */
- Xint days; /* number of days to consider for print command */
- Xtime_t seconds; /* that number of days in seconds */
- Xint max; /* maximum failure count for fail_max */
- X
- Xint uflg; /* set if user is a valid user id */
- Xint tflg; /* print is restricted to most recent days */
- Xstruct faillog faillog; /* scratch structure to play with ... */
- Xstruct stat statbuf; /* fstat buffer for file size */
- X
- Xextern int optind;
- Xextern char *optarg;
- Xextern char *asctime ();
- Xextern struct passwd *getpwuid ();
- Xextern struct passwd *getpwnam ();
- Xextern struct passwd *getpwent ();
- Xextern struct tm *localtime ();
- X
- X#define DAY (24L*3600L)
- X#define NOW (time ((time_t *) 0))
- X
- Xmain (argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X char *mode;
- X int c;
- X struct passwd *pwent;
- X
- X if (getuid () == 0) /* only root can update anything */
- X mode = "r+";
- X else /* all others can only look */
- X mode = "r";
- X
- X if ((fail = fopen (FAILFILE, mode)) == (FILE *) 0) {
- X perror (FAILFILE);
- X exit (1);
- X }
- X while ((c = getopt (argc, argv, "m:pru:t:")) != EOF) {
- X switch (c) {
- X case 'm':
- X max = atoi (optarg);
- X setmax ();
- X break;
- X case 'p':
- X print ();
- X break;
- X case 'r':
- X reset ();
- X break;
- X case 'u':
- X pwent = getpwnam (optarg);
- X if (! pwent) {
- X fprintf (stderr, "Unknown User: %s\n", optarg);
- X exit (1);
- X }
- X uflg++;
- X user = pwent->pw_uid;
- X break;
- X case 't':
- X days = atoi (optarg);
- X seconds = days * DAY;
- X tflg++;
- X break;
- X }
- X }
- X fclose (fail);
- X exit (0);
- X /*NOTREACHED*/
- X}
- X
- Xprint ()
- X{
- X int uid;
- X off_t offset;
- X
- X if (uflg) {
- X offset = user * sizeof faillog;
- X fstat (fileno (fail), &statbuf);
- X if (offset >= statbuf.st_size)
- X return;
- X
- X fseek (fail, (off_t) user * sizeof faillog, 0);
- X if (fread ((char *) &faillog, sizeof faillog, 1, fail) == 1)
- X print_one (&faillog, user);
- X else
- X perror (FAILFILE);
- X } else {
- X for (uid = 0;
- X fread ((char *) &faillog, sizeof faillog, 1, fail) == 1;
- X uid++) {
- X
- X if (faillog.fail_cnt == 0)
- X continue;
- X
- X if (tflg && NOW - faillog.fail_time > seconds)
- X continue;
- X
- X print_one (&faillog, uid);
- X }
- X }
- X}
- X
- Xprint_one (uid)
- Xint uid;
- X{
- X static int once;
- X char *cp;
- X struct tm *tm;
- X struct passwd *pwent;
- X
- X if (! once) {
- X printf ("Username Failures Maximum Latest\n");
- X once++;
- X }
- X pwent = getpwuid (uid);
- X tm = localtime (&faillog.fail_time);
- X cp = asctime (tm);
- X cp[24] = '\0';
- X
- X if (pwent) {
- X printf ("%-16s %4d %4d",
- X pwent->pw_name, faillog.fail_cnt, faillog.fail_max);
- X if (faillog.fail_time)
- X printf (" %s on %s\n", cp, faillog.fail_line);
- X else
- X putchar ('\n');
- X }
- X}
- X
- Xreset ()
- X{
- X int uid = 0;
- X
- X if (uflg)
- X reset_one (user);
- X else
- X for (uid = 0;reset_one (uid);uid++)
- X ;
- X}
- X
- Xreset_one (uid)
- Xint uid;
- X{
- X off_t offset;
- X
- X offset = uid * sizeof faillog;
- X fstat (fileno (fail), &statbuf);
- X if (offset >= statbuf.st_size)
- X return (0);
- X
- X if (fseek (fail, offset, 0) != 0) {
- X perror (FAILFILE);
- X return (0);
- X }
- X if (fread ((char *) &faillog, sizeof faillog, 1, fail) != 1) {
- X if (! feof (fail))
- X perror (FAILFILE);
- X
- X return (0);
- X }
- X if (faillog.fail_cnt == 0)
- X return (1); /* don't fill in no holes ... */
- X
- X faillog.fail_cnt = 0;
- X
- X if (fseek (fail, offset, 0) == 0
- X && fwrite ((char *) &faillog, sizeof faillog, 1, fail) == 1) {
- X fflush (fail);
- X return (1);
- X } else {
- X perror (FAILFILE);
- X }
- X return (0);
- X}
- X
- Xsetmax ()
- X{
- X struct passwd *pwent;
- X
- X if (uflg) {
- X setmax_one (user);
- X } else {
- X setpwent ();
- X while (pwent = getpwent ())
- X setmax_one (pwent->pw_uid);
- X }
- X}
- X
- Xsetmax_one (uid)
- Xint uid;
- X{
- X off_t offset;
- X
- X offset = uid * sizeof faillog;
- X
- X if (fseek (fail, offset, 0) != 0) {
- X perror (FAILFILE);
- X return;
- X }
- X if (fread ((char *) &faillog, sizeof faillog, 1, fail) != 1) {
- X if (! feof (fail))
- X perror (FAILFILE);
- X } else {
- X#ifndef BSD
- X memset ((char *) &faillog, '\0', sizeof faillog);
- X#else
- X bzero ((char *) &faillog, sizeof faillog);
- X#endif
- X }
- X faillog.fail_max = max;
- X
- X if (fseek (fail, offset, 0) == 0
- X && fwrite ((char *) &faillog, sizeof faillog, 1, fail) == 1)
- X fflush (fail);
- X else
- X perror (FAILFILE);
- X}
- END_OF_FILE
- if test 4879 -ne `wc -c <'faillog.c'`; then
- echo shar: \"'faillog.c'\" unpacked with wrong size!
- fi
- # end of 'faillog.c'
- fi
- if test -f 'groupdel.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'groupdel.c'\"
- else
- echo shar: Extracting \"'groupdel.c'\" \(4494 characters\)
- sed "s/^X//" >'groupdel.c' <<'END_OF_FILE'
- X/*
- X * Copyright 1991, John F. Haugh II
- X * All rights reserved.
- X *
- X * Permission is granted to copy and create derivative works for any
- X * non-commercial purpose, provided this copyright notice is preserved
- X * in all copies of source code, or included in human readable form
- X * and conspicuously displayed on all copies of object code or
- X * distribution media.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)groupdel.c 3.3 08:43:48 9/12/91";
- X#endif
- X
- X#include <sys/types.h>
- X#include <stdio.h>
- X#include <grp.h>
- X#include <ctype.h>
- X#include <fcntl.h>
- X
- X#ifdef BSD
- X#include <strings.h>
- X#else
- X#include <string.h>
- X#endif
- X
- X#include "config.h"
- X#include "shadow.h"
- X
- X#ifdef USE_SYSLOG
- X#include <syslog.h>
- X#endif
- X
- Xchar group_name[BUFSIZ];
- Xchar *Prog;
- X
- X#ifdef NDBM
- Xextern int gr_dbm_mode;
- Xextern int sg_dbm_mode;
- X#endif
- Xextern char *malloc();
- X
- Xextern struct group *getgrnam();
- Xextern int gr_lock();
- Xextern int gr_unlock();
- Xextern int gr_open();
- X
- X#ifdef SHADOWGRP
- Xextern int sgr_lock();
- Xextern int sgr_unlock();
- Xextern int sgr_open();
- X#endif
- X
- X/*
- X * usage - display usage message and exit
- X */
- X
- Xusage ()
- X{
- X fprintf (stderr, "usage: groupmod group\n");
- X exit (2);
- X}
- X
- X/*
- X * grp_update - update group file entries
- X *
- X * grp_update() writes the new records to the group files.
- X */
- X
- Xvoid
- Xgrp_update ()
- X{
- X struct group *ogrp;
- X
- X if (! gr_remove (group_name)) {
- X fprintf (stderr, "%s: error removing group entry\n", Prog);
- X exit (1);
- X }
- X#ifdef NDBM
- X
- X /*
- X * Update the DBM group file
- X */
- X
- X if (access ("/etc/group.pag", 0) == 0) {
- X if ((ogrp = getgrnam (group_name)) &&
- X ! gr_dbm_remove (ogrp)) {
- X fprintf (stderr, "%s: error removing group dbm entry\n",
- X Prog);
- X exit (1);
- X }
- X }
- X endgrent ();
- X#endif /* NDBM */
- X
- X#ifdef SHADOWGRP
- X
- X /*
- X * Delete the shadow group entries as well.
- X */
- X
- X if (! sgr_remove (group_name)) {
- X fprintf (stderr, "%s: error removing shadow group entry\n",
- X Prog);
- X exit (1);
- X }
- X#ifdef NDBM
- X
- X /*
- X * Update the DBM shadow group file
- X */
- X
- X if (access ("/etc/gshadow.pag", 0) == 0) {
- X if (! sgr_dbm_remove (group_name)) {
- X fprintf (stderr,
- X "%s: error removing shadow group dbm entry\n",
- X Prog);
- X exit (1);
- X }
- X }
- X endsgent ();
- X#endif /* NDBM */
- X#endif /* SHADOWGRP */
- X#ifdef USE_SYSLOG
- X syslog (LOG_INFO, "remove group `%s'\n", group_name);
- X#endif /* USE_SYSLOG */
- X}
- X
- X/*
- X * close_files - close all of the files that were opened
- X *
- X * close_files() closes all of the files that were opened for this
- X * new group. This causes any modified entries to be written out.
- X */
- X
- Xclose_files ()
- X{
- X if (! gr_close ()) {
- X fprintf (stderr, "%s: cannot rewrite group file\n", Prog);
- X exit (1);
- X }
- X (void) gr_unlock ();
- X#ifdef SHADOWGRP
- X if (! sgr_close ()) {
- X fprintf (stderr, "%s: cannot rewrite shadow group file\n",
- X Prog);
- X exit (1);
- X }
- X (void) sgr_unlock ();
- X#endif /* SHADOWGRP */
- X}
- X
- X/*
- X * open_files - lock and open the group files
- X *
- X * open_files() opens the two group files.
- X */
- X
- Xopen_files ()
- X{
- X if (! gr_lock ()) {
- X fprintf (stderr, "%s: unable to lock group file\n", Prog);
- X exit (1);
- X }
- X if (! gr_open (O_RDWR)) {
- X fprintf (stderr, "%s: unable to open group file\n", Prog);
- X exit (1);
- X }
- X#ifdef SHADOWGRP
- X if (! sgr_lock ()) {
- X fprintf (stderr, "%s: unable to lock shadow group file\n",
- X Prog);
- X exit (1);
- X }
- X if (! sgr_open (O_RDWR)) {
- X fprintf (stderr, "%s: unable to open shadow group file\n",
- X Prog);
- X exit (1);
- X }
- X#endif /* SHADOWGRP */
- X}
- X
- X/*
- X * main - groupdel command
- X *
- X * The syntax of the groupdel command is
- X *
- X * groupdel group
- X *
- X * The named group will be deleted.
- X */
- X
- Xmain (argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X
- X /*
- X * Get my name so that I can use it to report errors.
- X */
- X
- X if (Prog = strrchr (argv[0], '/'))
- X Prog++;
- X else
- X Prog = argv[0];
- X
- X if (argc != 2)
- X usage ();
- X
- X strncpy (group_name, argv[1], BUFSIZ);
- X
- X#ifdef USE_SYSLOG
- X openlog (Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
- X#endif /* USE_SYSLOG */
- X
- X /*
- X * The open routines for the DBM files don't use read-write
- X * as the mode, so we have to clue them in.
- X */
- X
- X#ifdef NDBM
- X gr_dbm_mode = O_RDWR;
- X#ifdef SHADOWGRP
- X sg_dbm_mode = O_RDWR;
- X#endif /* SHADOWGRP */
- X#endif /* NDBM */
- X
- X /*
- X * Start with a quick check to see if the group exists.
- X */
- X
- X if (! getgrnam (group_name)) {
- X fprintf (stderr, "%s: group %s does not exist\n",
- X Prog, group_name);
- X exit (9);
- X }
- X
- X /*
- X * Do the hard stuff - open the files, delete the group entries,
- X * then close and update the files.
- X */
- X
- X open_files ();
- X
- X grp_update ();
- X
- X close_files ();
- X exit (0);
- X /*NOTREACHED*/
- X}
- END_OF_FILE
- if test 4494 -ne `wc -c <'groupdel.c'`; then
- echo shar: \"'groupdel.c'\" unpacked with wrong size!
- fi
- # end of 'groupdel.c'
- fi
- if test -f 'gshadow.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'gshadow.c'\"
- else
- echo shar: Extracting \"'gshadow.c'\" \(4592 characters\)
- sed "s/^X//" >'gshadow.c' <<'END_OF_FILE'
- X/*
- X * Copyright 1990, 1991, John F. Haugh II
- X * All rights reserved.
- X *
- X * Permission is granted to copy and create derivative works for any
- X * non-commercial purpose, provided this copyright notice is preserved
- X * in all copies of source code, or included in human readable form
- X * and conspicuously displayed on all copies of object code or
- X * distribution media.
- X */
- X
- X#include "shadow.h"
- X#include "config.h"
- X#include <stdio.h>
- X#ifndef BSD
- X#include <string.h>
- X#include <memory.h>
- X#else
- X#include <strings.h>
- X#define strchr index
- X#define strrchr rindex
- X#endif
- X
- X#ifdef NDBM
- X#include <ndbm.h>
- X#include <fcntl.h>
- XDBM *sgr_dbm;
- Xint sg_dbm_mode = -1;
- Xstatic int dbmopened;
- Xstatic int dbmerror;
- X#endif
- X
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)gshadow.c 3.7 08:45:58 9/12/91";
- X#endif
- X
- X#define MAXMEM 1024
- X
- Xstatic FILE *shadow;
- Xstatic char *sgrpfile = "/etc/gshadow";
- Xstatic char sgrbuf[BUFSIZ*4];
- Xstatic char *members[MAXMEM+1];
- Xstatic char *admins[MAXMEM+1];
- Xstatic struct sgrp sgroup;
- X
- Xextern char *fgetsx();
- Xextern int fputsx();
- X
- X#define FIELDS 4
- X
- Xstatic char **
- Xlist (s, l)
- Xchar *s;
- Xchar **l;
- X{
- X int nmembers = 0;
- X
- X while (s && *s) {
- X l[nmembers++] = s;
- X if (s = strchr (s, ','))
- X *s++ = '\0';
- X }
- X l[nmembers] = (char *) 0;
- X return l;
- X}
- X
- Xvoid
- Xsetsgent ()
- X{
- X#ifdef NDBM
- X int mode;
- X#endif /* NDBM */
- X
- X if (shadow)
- X rewind (shadow);
- X else
- X shadow = fopen (GSHADOW, "r");
- X
- X /*
- X * Attempt to open the DBM files if they have never been opened
- X * and an error has never been returned.
- X */
- X
- X#ifdef NDBM
- X if (! dbmerror && ! dbmopened) {
- X char dbmfiles[BUFSIZ];
- X
- X strcpy (dbmfiles, sgrpfile);
- X strcat (dbmfiles, ".pag");
- X
- X if (sg_dbm_mode == -1)
- X mode = O_RDWR;
- X else
- X mode = (sg_dbm_mode == O_RDWR) ? O_RDWR:O_RDONLY;
- X
- X if (access (dbmfiles, 0) ||
- X (! (sgr_dbm = dbm_open (sgrpfile, mode, 0))))
- X dbmerror = 1;
- X else
- X dbmopened = 1;
- X }
- X#endif /* NDBM */
- X}
- X
- Xvoid
- Xendsgent ()
- X{
- X if (shadow)
- X (void) fclose (shadow);
- X
- X shadow = (FILE *) 0;
- X#ifdef NDBM
- X if (dbmopened && sgr_dbm) {
- X dbm_close (sgr_dbm);
- X dbmopened = 0;
- X sgr_dbm = 0;
- X }
- X#endif
- X}
- X
- Xstruct sgrp *
- Xsgetsgent (string)
- Xchar *string;
- X{
- X char *fields[FIELDS];
- X char *cp;
- X int atoi ();
- X long atol ();
- X int i;
- X
- X strncpy (sgrbuf, string, (int) sizeof sgrbuf - 1);
- X sgrbuf[sizeof sgrbuf - 1] = '\0';
- X
- X if (cp = strrchr (sgrbuf, '\n'))
- X *cp = '\0';
- X
- X for (cp = sgrbuf, i = 0;i < FIELDS && cp;i++) {
- X fields[i] = cp;
- X if (cp = strchr (cp, ':'))
- X *cp++ = '\0';
- X }
- X if (*cp || i != FIELDS)
- X return 0;
- X
- X sgroup.sg_name = fields[0];
- X sgroup.sg_passwd = fields[1];
- X sgroup.sg_adm = list (fields[2], admins);
- X sgroup.sg_mem = list (fields[3], members);
- X
- X return &sgroup;
- X}
- X
- Xstruct sgrp
- X*fgetsgent (fp)
- XFILE *fp;
- X{
- X char buf[sizeof sgrbuf];
- X
- X if (! fp)
- X return (0);
- X
- X if (fgetsx (buf, sizeof buf, fp) == (char *) 0)
- X return (0);
- X
- X return sgetsgent (buf);
- X}
- X
- Xstruct sgrp
- X*getsgent ()
- X{
- X if (! shadow)
- X setsgent ();
- X
- X return (fgetsgent (shadow));
- X}
- X
- Xstruct sgrp *
- Xgetsgnam (name)
- Xchar *name;
- X{
- X struct sgrp *sgrp;
- X#ifdef NDBM
- X datum key;
- X datum content;
- X#endif
- X
- X setsgent ();
- X
- X#ifdef NDBM
- X
- X /*
- X * If the DBM file are now open, create a key for this group and
- X * try to fetch the entry from the database. A matching record
- X * will be unpacked into a static structure and returned to
- X * the user.
- X */
- X
- X if (dbmopened) {
- X key.dsize = strlen (name);
- X key.dptr = name;
- X
- X content = dbm_fetch (sgr_dbm, key);
- X if (content.dptr != 0) {
- X memcpy (sgrbuf, content.dptr, content.dsize);
- X sgroup.sg_mem = members;
- X sgroup.sg_adm = admins;
- X sgr_unpack (sgrbuf, content.dsize, &sgroup);
- X return &sgroup;
- X }
- X }
- X#endif
- X while ((sgrp = getsgent ()) != (struct sgrp *) 0) {
- X if (strcmp (name, sgrp->sg_name) == 0)
- X return (sgrp);
- X }
- X return (0);
- X}
- X
- Xint
- Xputsgent (sgrp, fp)
- Xstruct sgrp *sgrp;
- XFILE *fp;
- X{
- X char buf[sizeof sgrbuf];
- X char *cp = buf;
- X int i;
- X
- X if (! fp || ! sgrp)
- X return -1;
- X
- X /*
- X * Copy the group name and passwd.
- X */
- X
- X strcpy (cp, sgrp->sg_name);
- X cp += strlen (cp);
- X *cp++ = ':';
- X
- X strcpy (cp, sgrp->sg_passwd);
- X cp += strlen (cp);
- X *cp++ = ':';
- X
- X /*
- X * Copy the administrators, separating each from the other
- X * with a ",".
- X */
- X
- X for (i = 0;sgrp->sg_adm[i];i++) {
- X if (i > 0)
- X *cp++ = ',';
- X
- X strcpy (cp, sgrp->sg_adm[i]);
- X cp += strlen (cp);
- X }
- X *cp++ = ':';
- X
- X /*
- X * Now do likewise with the group members.
- X */
- X
- X for (i = 0;sgrp->sg_mem[i];i++) {
- X if (i > 0)
- X *cp++ = ',';
- X
- X strcpy (cp, sgrp->sg_mem[i]);
- X cp += strlen (cp);
- X }
- X *cp++ = '\n';
- X *cp = '\0';
- X
- X /*
- X * Output using the function which understands the line
- X * continuation conventions.
- X */
- X
- X return fputsx (buf, fp);
- X}
- END_OF_FILE
- if test 4592 -ne `wc -c <'gshadow.c'`; then
- echo shar: \"'gshadow.c'\" unpacked with wrong size!
- fi
- # end of 'gshadow.c'
- fi
- if test -f 'obscure.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'obscure.c'\"
- else
- echo shar: Extracting \"'obscure.c'\" \(3472 characters\)
- sed "s/^X//" >'obscure.c' <<'END_OF_FILE'
- X/*
- X * Copyright 1989, 1990, 1991, John F. Haugh II
- X * All rights reserved.
- X *
- X * Permission is granted to copy and create derivative works for any
- X * non-commercial purpose, provided this copyright notice is preserved
- X * in all copies of source code, or included in human readable form
- X * and conspicuously displayed on all copies of object code or
- X * distribution media.
- X */
- X
- X#include <ctype.h>
- X#ifndef BSD
- X#include <string.h>
- X#include <memory.h>
- X#else
- X#include <strings.h>
- X#define strchr index
- X#define strrchr rindex
- X#endif
- X#include "config.h"
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)obscure.c 3.5 07:43:55 9/17/91";
- X#endif
- X
- Xextern int getdef_bool();
- Xextern int getdef_num();
- X
- X#ifdef NEED_STRSTR
- X/*
- X * strstr - find substring in string
- X */
- X
- Xchar *
- Xstrstr (string, pattern)
- Xchar *string;
- Xchar *pattern;
- X{
- X char *cp;
- X int len;
- X
- X len = strlen (pattern);
- X
- X for (cp = string;cp = strchr (cp, *pattern);) {
- X if (strncmp (cp, pattern, len) == 0)
- X return cp;
- X
- X cp++;
- X }
- X return 0;
- X}
- X#endif
- X
- X/*
- X * Obscure - see if password is obscure enough.
- X *
- X * The programmer is encouraged to add as much complexity to this
- X * routine as desired. Included are some of my favorite ways to
- X * check passwords.
- X */
- X
- X/*ARGSUSED*/
- Xint obscure (old, new)
- Xchar *old;
- Xchar *new;
- X{
- X int i;
- X char oldmono[32];
- X char newmono[32];
- X char wrapped[64];
- X
- X if (old[0] == '\0')
- X return (1);
- X
- X if ( strlen(new) < getdef_num("PASS_MIN_LEN", 0) ) {
- X printf ("Too short. ");
- X return (0);
- X }
- X
- X /*
- X * Remaining checks are optional.
- X */
- X if ( !getdef_bool("OBSCURE_CHECKS_ENAB") )
- X return (1);
- X
- X for (i = 0;new[i];i++)
- X newmono[i] = tolower (new[i]);
- X
- X for (i = 0;old[i];i++)
- X oldmono[i] = tolower (old[i]);
- X
- X if (strcmp (new, old) == 0) { /* the same */
- X printf ("No Change. ");
- X return (0);
- X }
- X if (palindrome (newmono, oldmono)) /* a palindrome */
- X return (0);
- X
- X if (strcmp (newmono, oldmono) == 0) { /* case shifted */
- X printf ("Case changes only. ");
- X return (0);
- X }
- X if (similiar (newmono, oldmono)) /* jumbled version */
- X return (0);
- X
- X if (simple (old, new)) /* keyspace size */
- X return (0);
- X
- X strcpy (wrapped, oldmono);
- X strcat (wrapped, oldmono);
- X if (strstr (wrapped, newmono)) {
- X printf ("Rotated. ");
- X return (0);
- X }
- X return (1);
- X}
- X
- X/*
- X * can't be a palindrome - like `R A D A R' or `M A D A M'
- X */
- X
- X/*ARGSUSED*/
- Xint palindrome (old, new)
- Xchar *old;
- Xchar *new;
- X{
- X int i, j;
- X
- X i = strlen (new);
- X
- X for (j = 0;j < i;j++)
- X if (new[i - j - 1] != new[j])
- X return (0);
- X
- X printf ("A palindrome. ");
- X return (1);
- X}
- X
- X/*
- X * more than half of the characters are different ones.
- X */
- X
- X/*ARGSUSED*/
- Xint similiar (old, new)
- Xchar *old;
- Xchar *new;
- X{
- X int i, j;
- X char *strchr ();
- X
- X for (i = j = 0;new[i] && old[i];i++)
- X if (strchr (new, tolower (old[i])))
- X j++;
- X
- X if (i >= j * 2)
- X return (0);
- X
- X printf ("Too similiar. ");
- X return (1);
- X}
- X
- X/*
- X * a nice mix of characters.
- X */
- X
- X/*ARGSUSED*/
- Xint simple (old, new)
- Xchar *old;
- Xchar *new;
- X{
- X int digits = 0;
- X int uppers = 0;
- X int lowers = 0;
- X int others = 0;
- X int size;
- X int i;
- X
- X for (i = 0;new[i];i++) {
- X if (isdigit (new[i]))
- X digits++;
- X else if (isupper (new[i]))
- X uppers++;
- X else if (islower (new[i]))
- X lowers++;
- X else
- X others++;
- X }
- X
- X /*
- X * The scam is this - a password of only one character type
- X * must be 8 letters long. Two types, 7, and so on.
- X */
- X
- X size = 9;
- X if (digits) size--;
- X if (uppers) size--;
- X if (lowers) size--;
- X if (others) size--;
- X
- X if (size <= i)
- X return 0;
- X
- X printf ("Too Simple. ");
- X return 1;
- X}
- END_OF_FILE
- if test 3472 -ne `wc -c <'obscure.c'`; then
- echo shar: \"'obscure.c'\" unpacked with wrong size!
- fi
- # end of 'obscure.c'
- fi
- if test -f 'pwconv.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'pwconv.c'\"
- else
- echo shar: Extracting \"'pwconv.c'\" \(4445 characters\)
- sed "s/^X//" >'pwconv.c' <<'END_OF_FILE'
- X/*
- X * Copyright 1989, 1990, 1991, John F. Haugh II
- X * All rights reserved.
- X *
- X * Permission is granted to copy and create derivative works for any
- X * non-commercial purpose, provided this copyright notice is preserved
- X * in all copies of source code, or included in human readable form
- X * and conspicuously displayed on all copies of object code or
- X * distribution media.
- X *
- X * pwconv - convert and update shadow password files
- X *
- X * Pwconv copies the old password file information to a new shadow
- X * password file, merging entries from an optional existing shadow
- X * file.
- X *
- X * The new password file is left in npasswd, the new shadow file is
- X * left in nshadow. Existing shadow entries are copied as is.
- X * New entries are created with passwords which expire in MAXDAYS days,
- X * with a last changed date of today, unless password aging
- X * information was already present. Likewise, the minimum number of
- X * days before which the password may be changed is controlled by
- X * MINDAYS. The number of warning days is set to WARNAGE if that
- X * macro exists. Entries with blank passwordsare not copied to the
- X * shadow file at all.
- X */
- X
- X#include <sys/types.h>
- X#include <stdio.h>
- X#include <fcntl.h>
- X#include "pwd.h"
- X#ifndef BSD
- X#include <string.h>
- X#else
- X#define strchr index
- X#define strrchr rindex
- X#include <strings.h>
- X#endif
- X#include "config.h"
- X#include "shadow.h"
- X
- X#ifndef lint
- Xstatic char _sccsid[] = "@(#)pwconv.c 3.4 07:43:52 9/17/91";
- X#endif
- X
- Xchar buf[BUFSIZ];
- X
- Xlong time ();
- Xlong a64l ();
- Xextern int getdef_num();
- X
- Xint main ()
- X{
- X long today;
- X struct passwd *pw;
- X struct passwd *sgetpwent ();
- X FILE *pwd;
- X FILE *npwd;
- X FILE *shadow;
- X struct spwd *spwd;
- X struct spwd tspwd;
- X int fd;
- X char *cp;
- X
- X if (! (pwd = fopen (PWDFILE, "r"))) {
- X perror (PWDFILE);
- X exit (1);
- X }
- X unlink ("npasswd");
- X if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0 ||
- X ! (npwd = fdopen (fd, "w"))) {
- X perror ("npasswd");
- X exit (1);
- X }
- X unlink ("nshadow");
- X if ((fd = open ("nshadow", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
- X ! (shadow = fdopen (fd, "w"))) {
- X perror ("nshadow");
- X (void) unlink ("npasswd");
- X (void) unlink ("nshadow");
- X exit (1);
- X }
- X
- X (void) time (&today);
- X today /= (24L * 60L * 60L);
- X
- X while (fgets (buf, BUFSIZ, pwd) == buf) {
- X if (cp = strrchr (buf, '\n'))
- X *cp = '\0';
- X
- X if (buf[0] == '#') { /* comment line */
- X (void) fprintf (npwd, "%s\n", buf);
- X continue;
- X }
- X if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
- X (void) fprintf (npwd, "%s\n", buf);
- X continue;
- X }
- X if (pw->pw_passwd[0] == '\0') { /* no password, skip */
- X (void) fprintf (npwd, "%s\n", buf);
- X continue;
- X }
- X setspent (); /* rewind old shadow file */
- X
- X if (spwd = getspnam (pw->pw_name)) {
- X if (putspent (spwd, shadow)) { /* copy old entry */
- X perror ("nshadow");
- X goto error;
- X }
- X } else { /* need a new entry. */
- X tspwd.sp_namp = pw->pw_name;
- X tspwd.sp_pwdp = pw->pw_passwd;
- X pw->pw_passwd = "x";
- X#ifdef ATT_AGE
- X if (pw->pw_age) { /* copy old password age stuff */
- X if (strlen (pw->pw_age) >= 2) {
- X tspwd.sp_min = c64i (pw->pw_age[1]);
- X tspwd.sp_max = c64i (pw->pw_age[0]);
- X } else {
- X tspwd.sp_min = tspwd.sp_max = -1;
- X }
- X if (strlen (pw->pw_age) == 4)
- X tspwd.sp_lstchg = a64l (&pw->pw_age[2]);
- X else
- X tspwd.sp_lstchg = -1;
- X
- X /*
- X * Convert weeks to days
- X */
- X
- X if (tspwd.sp_min != -1)
- X tspwd.sp_min *= 7;
- X
- X if (tspwd.sp_max != -1)
- X tspwd.sp_max *= 7;
- X
- X if (tspwd.sp_lstchg != -1)
- X tspwd.sp_lstchg *= 7;
- X } else
- X#endif /* ATT_AGE */
- X { /* fake up new password age stuff */
- X tspwd.sp_max =
- X getdef_num("PASS_MAX_DAYS", 10000);
- X tspwd.sp_min = getdef_num("PASS_MIN_DAYS", 0);
- X tspwd.sp_lstchg = today;
- X }
- X tspwd.sp_warn = getdef_num("PASS_WARN_AGE", -1);
- X tspwd.sp_inact = tspwd.sp_expire = tspwd.sp_flag = -1;
- X if (putspent (&tspwd, shadow)) { /* output entry */
- X perror ("nshadow");
- X goto error;
- X }
- X }
- X (void) fprintf (npwd, "%s:%s:%d:%d:%s:%s:",
- X pw->pw_name, pw->pw_passwd,
- X pw->pw_uid, pw->pw_gid,
- X pw->pw_gecos, pw->pw_dir);
- X
- X if (fprintf (npwd, "%s\n",
- X pw->pw_shell ? pw->pw_shell:"") == EOF) {
- X perror ("npasswd");
- X goto error;
- X }
- X }
- X endspent ();
- X
- X if (ferror (npwd) || ferror (shadow)) {
- X perror ("pwconv");
- Xerror:
- X (void) unlink ("npasswd");
- X (void) unlink ("nshadow");
- X exit (1);
- X }
- X (void) fclose (pwd);
- X (void) fclose (npwd);
- X (void) fclose (shadow);
- X
- X exit (0);
- X}
- END_OF_FILE
- if test 4445 -ne `wc -c <'pwconv.c'`; then
- echo shar: \"'pwconv.c'\" unpacked with wrong size!
- fi
- # end of 'pwconv.c'
- fi
- if test -f 'setup.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'setup.c'\"
- else
- echo shar: Extracting \"'setup.c'\" \(4293 characters\)
- sed "s/^X//" >'setup.c' <<'END_OF_FILE'
- X/*
- X * Copyright 1989, 1990, 1991, John F. Haugh II
- X * All rights reserved.
- X *
- X * Permission is granted to copy and create derivative works for any
- X * non-commercial purpose, provided this copyright notice is preserved
- X * in all copies of source code, or included in human readable form
- X * and conspicuously displayed on all copies of object code or
- X * distribution media.
- X */
- X
- X#include <sys/types.h>
- X#include <stdio.h>
- X#include <utmp.h>
- X
- X#ifdef BSD
- X#include <strings.h>
- X#define strchr index
- X#else
- X#include <string.h>
- X#include <memory.h>
- X#endif
- X
- X#include "config.h"
- X#include "pwd.h"
- X
- X#ifdef USE_SYSLOG
- X#include <syslog.h>
- X
- X#ifndef LOG_WARN
- X#define LOG_WARN LOG_WARNING
- X#endif
- X#endif
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)setup.c 3.8 07:43:12 9/17/91";
- X#endif
- X
- X#ifndef SU
- Xextern struct utmp utent;
- X#endif
- X
- Xlong strtol ();
- X#ifdef HAVE_ULIMIT
- Xlong ulimit ();
- X#endif
- X
- Xvoid addenv ();
- Xextern char *getdef_str();
- Xextern int getdef_bool();
- Xextern int getdef_num();
- X
- X/*
- X * setup - initialize login environment
- X *
- X * setup() performs the following steps -
- X *
- X * set the login tty to be owned by the new user ID with TTYPERM modes
- X * change to the user's home directory
- X * set the process nice, ulimit, and umask from the password file entry
- X * set the group ID to the value from the password file entry
- X * set the supplementary group IDs
- X * set the user ID to the value from the password file entry
- X * set the HOME, SHELL, MAIL, PATH, and LOGNAME or USER environmental
- X * variables.
- X */
- X
- Xvoid setup (info)
- Xstruct passwd *info;
- X{
- X extern int errno;
- X char buf[BUFSIZ];
- X#ifndef SU
- X char tty[30];
- X#endif
- X char *cp;
- X int i;
- X long l;
- X
- X#ifndef SU
- X (void) strcat (strcpy (tty, "/dev/"), utent.ut_line);
- X
- X if (chown (tty, info->pw_uid, info->pw_gid) ||
- X chmod (tty, getdef_num("TTYPERM", 0622))) {
- X (void) sprintf (buf, "Unable to change tty %s", tty);
- X#ifdef USE_SYSLOG
- X syslog (LOG_WARN, "unable to change tty `%s' for user `%s'\n",
- X tty, info->pw_name);
- X closelog ();
- X#endif
- X perror (buf);
- X exit (errno);
- X }
- X#endif
- X if (chdir (info->pw_dir) == -1) {
- X (void) sprintf (buf, "Unable to cd to \"%s\"", info->pw_dir);
- X#ifdef USE_SYSLOG
- X syslog (LOG_WARN, "unable to cd to `%s' for user `%s'\n",
- X info->pw_dir, info->pw_name);
- X closelog ();
- X#endif
- X perror (buf);
- X exit (errno);
- X }
- X if ( getdef_bool("QUOTAS_ENAB") ) {
- X for (cp = info->pw_gecos ; cp != NULL ; cp = strchr (cp, ',')) {
- X if (*cp == ',')
- X cp++;
- X
- X if (strncmp (cp, "pri=", 4) == 0) {
- X i = atoi (cp + 4);
- X if (i >= -20 && i <= 20)
- X (void) nice (i);
- X
- X continue;
- X }
- X#ifdef HAVE_ULIMIT
- X if (strncmp (cp, "ulimit=", 7) == 0) {
- X l = strtol (cp + 7, (char **) 0, 10);
- X (void) ulimit (2, l);
- X
- X continue;
- X }
- X#endif
- X if (strncmp (cp, "umask=", 6) == 0) {
- X i = strtol (cp + 6, (char **) 0, 8) & 0777;
- X (void) umask (i);
- X
- X continue;
- X }
- X }
- X }
- X if (setgid (info->pw_gid) == -1) {
- X puts ("Bad group id");
- X#ifdef USE_SYSLOG
- X syslog (LOG_WARN, "bad group ID `%d' for user `%s'\n",
- X info->pw_gid, info->pw_name);
- X closelog ();
- X#endif
- X exit (errno);
- X }
- X#if NGROUPS > 1
- X if(initgroups(info->pw_name,info->pw_gid) == -1) {
- X puts ("initgroups failure");
- X#ifdef USE_SYSLOG
- X syslog (LOG_WARN, "initgroups failed for user `%s'\n",
- X info->pw_name);
- X closelog ();
- X#endif
- X exit (errno);
- X }
- X#endif /* NGROUPS > 1 */
- X#ifndef BSD
- X if (setuid (info->pw_uid))
- X#else
- X if (setreuid (info->pw_uid, info->pw_uid))
- X#endif
- X {
- X puts ("Bad user id");
- X#ifdef USE_SYSLOG
- X syslog (LOG_WARN, "bad user ID `%d' for user `%s'\n",
- X info->pw_uid, info->pw_name);
- X closelog ();
- X#endif
- X exit (errno);
- X }
- X (void) strcat (strcpy (buf, "HOME="), info->pw_dir);
- X addenv (buf);
- X
- X if (info->pw_shell == (char *) 0 || ! *info->pw_shell)
- X info->pw_shell = "/bin/sh";
- X
- X (void) strcat (strcpy (buf, "SHELL="), info->pw_shell);
- X addenv (buf);
- X
- X cp = getdef_str( info->pw_uid == 0 ? "ENV_SUPATH" : "ENV_PATH" );
- X addenv( cp != NULL ? cp : "PATH=/bin:/usr/bin" );
- X
- X#if defined(BSD) || defined(SUN)
- X (void) strcat (strcpy (buf, "USER="), info->pw_name);
- X#else
- X (void) strcat (strcpy (buf, "LOGNAME="), info->pw_name);
- X#endif /* BSD || SUN */
- X addenv (buf);
- X
- X if ( (cp=getdef_str("MAIL_DIR")) == NULL )
- X cp = "/usr/spool/mail";
- X (void) strcat (strcat (strcat (strcpy (buf,
- X "MAIL="), cp), "/"), info->pw_name);
- X addenv (buf);
- X}
- END_OF_FILE
- if test 4293 -ne `wc -c <'setup.c'`; then
- echo shar: \"'setup.c'\" unpacked with wrong size!
- fi
- # end of 'setup.c'
- fi
- if test -f 'sulogin.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sulogin.c'\"
- else
- echo shar: Extracting \"'sulogin.c'\" \(3355 characters\)
- sed "s/^X//" >'sulogin.c' <<'END_OF_FILE'
- X/*
- X * Copyright 1989, 1990, 1991, John F. Haugh II
- X * All rights reserved.
- X *
- X * Permission is granted to copy and create derivative works for any
- X * non-commercial purpose, provided this copyright notice is preserved
- X * in all copies of source code, or included in human readable form
- X * and conspicuously displayed on all copies of object code or
- X * distribution media.
- X */
- X
- X#include <sys/types.h>
- X#include <stdio.h>
- X#include "pwd.h"
- X#include <utmp.h>
- X#ifdef BSD
- X#include <strings.h>
- X#define strchr index
- X#define strrchr rindex
- X#else
- X#include <string.h>
- X#include <memory.h>
- X#endif
- X#include "config.h"
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)sulogin.c 3.7 07:43:27 9/17/91";
- X#endif
- X
- Xchar name[BUFSIZ];
- Xchar pass[BUFSIZ];
- Xchar home[BUFSIZ];
- Xchar prog[BUFSIZ];
- Xchar mail[BUFSIZ];
- X
- Xstruct passwd pwent;
- Xstruct utmp utent;
- X
- X#ifndef MAXENV
- X#define MAXENV 64
- X#endif
- X
- Xchar *newenvp[MAXENV];
- Xint newenvc = 0;
- Xint maxenv = MAXENV;
- Xextern char **environ;
- Xextern char *getpass();
- X
- Xextern char *getdef_str();
- X
- X#ifndef ALARM
- X#define ALARM 60
- X#endif
- X
- X#ifndef RETRIES
- X#define RETRIES 3
- X#endif
- X
- X/*ARGSUSED*/
- Xint main (argc, argv, envp)
- Xint argc;
- Xchar **argv;
- Xchar **envp;
- X{
- X char *getenv ();
- X char *ttyname ();
- X char *getpass ();
- X char *tz ();
- X char *cp;
- X
- X if (access (PWDFILE, 0) == -1) { /* must be a password file! */
- X printf ("No password file\n");
- X exit (1);
- X }
- X#ifdef NDEBUG
- X if (getppid () != 1) /* parent must be INIT */
- X exit (1);
- X#endif
- X if (! isatty (0) || ! isatty (1) || ! isatty (2))
- X exit (1); /* must be a terminal */
- X
- X while (*envp) /* add inherited environment, */
- X addenv (*envp++); /* some variables change later */
- X
- X if (cp = getdef_str("ENV_TZ"))
- X addenv (*cp == '/' ? tz(cp) : cp);
- X if (cp = getdef_str("ENV_HZ"))
- X addenv (cp); /* set the default $HZ, if one */
- X (void) strcpy (name, "root"); /* KLUDGE!!! */
- X
- X alarm (ALARM); /* only wait so long ... */
- X while (1) { /* repeatedly get login/password pairs */
- X entry (name, &pwent); /* get entry from password file */
- X if (pwent.pw_name == (char *) 0) {
- X printf ("No password entry for 'root'\n");
- X exit (1);
- X }
- X
- X /*
- X * Here we prompt for the root password, or if no password is
- X * given we just exit.
- X */
- X
- X /* get a password for root */
- X if (! (cp = getpass ("Type control-d for normal startup,\n\
- X(or give root password for system maintenance):")))
- X exit (0);
- X else
- X strcpy (pass, cp);
- X
- X if (valid (pass, &pwent)) /* check encrypted passwords ... */
- X break; /* ... encrypted passwords matched */
- X
- X puts ("Login incorrect");
- X }
- X alarm (0);
- X environ = newenvp; /* make new environment active */
- X
- X puts ("Entering System Maintenance Mode");
- X
- X /*
- X * Normally there would be a utmp entry for login to mung on
- X * to get the tty name, date, etc. from. We don't need all that
- X * stuff because we won't update the utmp or wtmp files. BUT!,
- X * we do need the tty name so we can set the permissions and
- X * ownership.
- X */
- X
- X if (cp = ttyname (0)) { /* found entry in /dev/ */
- X if (strrchr (cp, '/') != (char *) 0)
- X strcpy (utent.ut_line, strrchr (cp, '/') + 1);
- X else
- X strcpy (utent.ut_line, cp);
- X }
- X if (getenv ("IFS")) /* don't export user IFS ... */
- X addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */
- X
- X setup (&pwent); /* set UID, GID, HOME, etc ... */
- X
- X shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */
- X /*NOTREACHED*/
- X}
- END_OF_FILE
- if test 3355 -ne `wc -c <'sulogin.c'`; then
- echo shar: \"'sulogin.c'\" unpacked with wrong size!
- fi
- # end of 'sulogin.c'
- fi
- if test -f 'useradd.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'useradd.1'\"
- else
- echo shar: Extracting \"'useradd.1'\" \(4618 characters\)
- sed "s/^X//" >'useradd.1' <<'END_OF_FILE'
- X.\" Copyright 1991, John F. Haugh II
- X.\" All rights reserved.
- X.\"
- X.\" Permission is granted to copy and create derivative works for any
- X.\" non-commercial purpose, provided this copyright notice is preserved
- X.\" in all copies of source code, or included in human readable form
- X.\" and conspicuously displayed on all copies of object code or
- X.\" distribution media.
- X.\"
- X.\" @(#)useradd.1 3.1 07:45:46 7/13/91
- X.\"
- X.TH USERADD 1M
- X.SH NAME
- Xuseradd \- Create a new user or update default new user information
- X.SH SYNOPSIS
- X.B useradd
- X[ \fB-c\fI comment\fR ]
- X[ \fB-d\fI home_dir\fR ]
- X[ \fB-e\fI expire_date\fR ]
- X[ \fB-f\fI inactive_time\fR ]
- X[ \fB-g\fI initial_group\fR ]
- X[ \fB-G\fI group[,...]\fR ]
- X[ \fB-m\fR [ \fB-k\fI skeleton_dir\fR ] ]
- X[ \fB-s\fI shell\fR ]
- X[ \fB-u\fI uid \fR[ \fB-o\fR ] ]
- X.I login
- X.sp 1
- X.B useradd
- X\fB-D\fR
- X[ \fB-g\fI default_group\fR ]
- X[ \fB-b\fI default_home\fR ]
- X[ \fB-f\fI default_inactive\fR ]
- X[ \fB-e\fI default_exiration\fR ]
- X.SH DESCRIPTION
- X.SS Creating New Users
- XWhen invoked without the \fB-D\fR option, the \fIuseradd\fR command
- Xcreates a new user account using the values specified on the
- Xcommand line and the default values from the system.
- XThe new user account will be entered into the system files as needed,
- Xthe home directory will be created, and initial files copied, depending
- Xon the command line options.
- XThe options which apply to the \fIuseradd\fR command are
- X.IP "\fB-d \fIhome_dir\fR"
- XThe new user will be created using \fIhome_dir\fR as the value for
- Xthe user's login directory.
- XThe default is to append the \fIlogin\fR name to \fIdefault_home\fR
- Xand use that as the login directory name.
- X.IP "\fB-e \fIexpire_date\fR"
- XThe date on which the user account will be disabled.
- XThe date is specified in the format \fIMM/DD/YY\fR.
- X.IP "\fB-f \fIinactive_days\fR"
- XThe number of days after a password expires until the account
- Xis permanently disabled.
- XA value of 0 disables the account as soon as the password has
- Xexpired, and a value of -1 disables the feature.
- XThe default value is -1.
- X.IP "\fB-g \fIinitial_group\fR"
- XThe group name or number of the user's initial login group.
- XThe group name must exist. A group number must refer to an
- Xalready existing group.
- XThe default group number is 1.
- X.IP "\fB-G \fIgroup,[...]\fR"
- XA list of supplementary groups which the user is also a member
- Xof.
- XEach group is separated from the next by a comma, with no
- Xintervening whitespace.
- XThe groups are subject to the same restrictions as the group
- Xgiven with the \fB-g\fR option.
- XThe default is for the user to belong only to the initial group.
- X.IP \fB-m\fR
- XThe user's home directory will be created if it does not exist.
- XThe files contained in \fIskeleton_dir\fR will be copied to the
- Xhome directory if the \fB-k\fR option is used.
- XThe \fB-k\fR option is only valid in conjunction with the \fB-m\fR
- Xoption.
- XThe default is to not create the directory and to not copy any
- Xfiles.
- X.IP "\fB-s \fIshell\fR"
- XThe name of the user's login shell.
- XThe default is to leave this field blank, which causes the system
- Xto select the default login shell.
- X.IP "\fB-u \fIuid\fR"
- XThe numerical value of the user's ID.
- XThis value must be unique, unless the \fI-o\fR option is used.
- XThe value must be non-negative.
- XThe default is to use the smallest ID value greater than 99 and
- Xgreater than every other user.
- XValues between 0 and 99 are typically reserved for system accounts.
- X.SS Changing the default values
- XWhen invoked with the \fB-D\fR option, \fIuseradd\fR will either
- Xdisplay the current default values, or update the default values
- Xfrom the command line.
- XThe valid options are
- X.IP "\fB-b \fIdefault_home\fR"
- XThe initial path prefix for a new user's home directory.
- XThe user's name will be affixed to the end of \fIdefault_home\fR
- Xto create the new directory name if the \fB-d\fI option is not
- Xused when creating a new account.
- X.IP "\fB-e \fIdefault_expire\fR"
- XThe number of days after a password is changed before it must
- Xbe changed again.
- X.IP "\fB-f \fIdefault_inactive\fR"
- XThe number of days after a password has expired before the
- Xaccount will be disabled.
- X.IP "\fB-g \fIdefault_group\fR"
- XThe group name or ID for a new user's initial group.
- XThe named group must exist, and a numerical group ID must have
- Xan existing entry .
- X.PP
- XIf no options are specified, \fIuseradd\fR displays the current
- Xdefault values.
- X.SH Files
- X/etc/passwd \- user account information
- X.br
- X/etc/shadow \- secure user account information
- X.br
- X/etc/group \- group information
- X.br
- X/etc/defaults/useradd \- default information
- X.SH SEE ALSO
- X\fBchfn(1), chsh(1), groupadd(1M), groupdel(1M), groupmod(1M),
- Xpasswd(1), userdel(1M), usermod(1M)
- END_OF_FILE
- if test 4618 -ne `wc -c <'useradd.1'`; then
- echo shar: \"'useradd.1'\" unpacked with wrong size!
- fi
- # end of 'useradd.1'
- fi
- if test -f 'utmp.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'utmp.c'\"
- else
- echo shar: Extracting \"'utmp.c'\" \(4259 characters\)
- sed "s/^X//" >'utmp.c' <<'END_OF_FILE'
- X/*
- X * Copyright 1989, 1990, 1991, John F. Haugh II
- X * All rights reserved.
- X *
- X * Permission is granted to copy and create derivative works for any
- X * non-commercial purpose, provided this copyright notice is preserved
- X * in all copies of source code, or included in human readable form
- X * and conspicuously displayed on all copies of object code or
- X * distribution media.
- X */
- X
- X#include <sys/types.h>
- X#include <utmp.h>
- X#include <fcntl.h>
- X#ifndef BSD
- X#include <string.h>
- X#include <memory.h>
- X#define bzero(a,n) memset(a, 0, n)
- X#else
- X#include <strings.h>
- X#define strchr index
- X#define strrchr rindex
- X#endif
- X#include <stdio.h>
- X#include "config.h"
- X
- X#if defined(SUN) || defined(BSD)
- X#ifndef WTMP_FILE
- X#define WTMP_FILE "/usr/adm/wtmp"
- X#endif
- X#endif /* SUN || BSD */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)utmp.c 3.12 07:43:36 9/17/91";
- X#endif
- X
- Xextern struct utmp utent;
- X
- Xextern struct utmp *getutent();
- Xextern struct utmp *getutline();
- Xextern void setutent();
- Xextern void endutent();
- Xextern time_t time();
- Xextern char *ttyname();
- Xextern long lseek();
- X
- X#define NO_UTENT \
- X "No utmp entry. You must exec \"login\" from the lowest level \"sh\""
- X#define NO_TTY \
- X "Unable to determine your tty name."
- X
- X/*
- X * checkutmp - see if utmp file is correct for this process
- X *
- X * System V is very picky about the contents of the utmp file
- X * and requires that a slot for the current process exist.
- X * The utmp file is scanned for an entry with the same process
- X * ID. If no entry exists the process exits with a message.
- X *
- X * The "picky" flag is for network and other logins that may
- X * use special flags. It allows the pid checks to be overridden.
- X * This means that getty should never invoke login with any
- X * command line flags.
- X */
- X
- Xvoid
- Xcheckutmp (picky)
- Xint picky;
- X{
- X char *line;
- X#ifdef USG
- X struct utmp *ut;
- X#ifndef NDEBUG
- X int pid = getppid ();
- X#else
- X int pid = getpid ();
- X#endif
- X#endif
- X
- X#ifndef SUN
- X setutent ();
- X#endif /* SUN */
- X
- X#ifdef USG
- X if (picky) {
- X while (ut = getutent ())
- X if (ut->ut_pid == pid)
- X break;
- X
- X if (ut)
- X utent = *ut;
- X
- X endutent ();
- X
- X if (! ut || utent.ut_pid != pid) {
- X (void) puts (NO_UTENT);
- X exit (1);
- X }
- X if (utent.ut_line[0] == '\0') {
- X if (! (line = ttyname (0))) {
- X (void) puts (NO_TTY);
- X exit (1);
- X }
- X if (strncmp (line, "/dev/", 5) == 0)
- X line += 5;
- X (void) strncpy (utent.ut_line, line,
- X (int) sizeof utent.ut_line);
- X }
- X } else {
- X if (! (line = ttyname (0))) {
- X puts (NO_TTY);
- X exit (1);
- X }
- X if (strncmp (line, "/dev/", 5) == 0)
- X line += 5;
- X
- X (void) strncpy (utent.ut_line, line,
- X (int) sizeof utent.ut_line);
- X if (ut = getutline (&utent))
- X (void) strncpy (utent.ut_id, ut->ut_id,
- X (int) sizeof ut->ut_id);
- X
- X (void) strcpy (utent.ut_user, "LOGIN");
- X utent.ut_pid = getpid ();
- X utent.ut_type = LOGIN_PROCESS;
- X (void) time (&utent.ut_time);
- X }
- X#else /* !USG */
- X bzero (&utent, sizeof utent);
- X if (! (line = ttyname (0))) {
- X puts (NO_TTY);
- X exit (1);
- X }
- X if (strncmp (line, "/dev/", 5))
- X line += 5;
- X
- X (void) strncpy (utent.ut_line, line, sizeof utent.ut_line);
- X (void) time (&utent.ut_time);
- X#endif /* !USG */
- X}
- X
- X/*
- X * setutmp - put a USER_PROCESS entry in the utmp file
- X *
- X * setutmp changes the type of the current utmp entry to
- X * USER_PROCESS. the wtmp file will be updated as well.
- X */
- X
- Xvoid
- Xsetutmp (name, line)
- Xchar *name;
- Xchar *line;
- X{
- X struct utmp utmp;
- X int fd;
- X int found = 0;
- X
- X if (! (fd = open ("/etc/utmp", O_RDWR)))
- X return;
- X
- X while (! found && read (fd, &utmp, sizeof utmp) == sizeof utmp) {
- X if (! strncmp (line, utmp.ut_line, (int) sizeof utmp.ut_line))
- X found++;
- X }
- X if (! found) {
- X (void) bzero (&utmp, sizeof utmp);
- X (void) strncpy (utmp.ut_line, line, (int) sizeof utmp.ut_line);
- X }
- X#if defined(SUN) || defined(BSD)
- X (void) strncpy (utmp.ut_name, name, (int) sizeof utent.ut_name);
- X#else /* SUN */
- X (void) strncpy (utmp.ut_user, name, (int) sizeof utent.ut_user);
- X utmp.ut_type = USER_PROCESS;
- X utmp.ut_pid = getpid ();
- X#endif /* SUN || BSD */
- X (void) time (&utmp.ut_time);
- X
- X if (found)
- X lseek (fd, (long) - sizeof utmp, 1);
- X
- X (void) write (fd, &utmp, sizeof utmp);
- X (void) close (fd);
- X
- X if ((fd = open (WTMP_FILE, O_WRONLY|O_APPEND)) >= 0) {
- X (void) write (fd, &utmp, sizeof utmp);
- X (void) close (fd);
- X }
- X utent = utmp;
- X}
- END_OF_FILE
- if test 4259 -ne `wc -c <'utmp.c'`; then
- echo shar: \"'utmp.c'\" unpacked with wrong size!
- fi
- # end of 'utmp.c'
- fi
- echo shar: End of archive 8 \(of 11\).
- cp /dev/null ark8isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 11 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-